/*
 * @Descripttion:
 * @version:
 * @Author: chenbolin@msn.cn
 * @Date: 2021-05-20 10:35:50
 * @LastEditors: chenbolin@msn.cn
 * @LastEditTime: 2023-10-27 18:08:12
 */
#include "HalUart.h"
// #include "stm32f1xx_hal_dma.h"

typedef struct
{
    uint8_t recvBuff[1];
    // volatile uint8_t txCpltFlag;
    UART_HandleTypeDef *huart;
    HalUartConfig_t config;
} HalUart_t;

#define HAL_UART_TRANSMIT_TIMEOUT 2000

extern UART_HandleTypeDef huart3;

static HalUart_t g_uart[HAL_UART_COUNT];

void HalUartWrite(uint8_t uartNum, const uint8_t *data, uint16_t len)
{
    HalUart_t *uart = &g_uart[uartNum];
//    int timeout = len < 10 ? 1 : (len + 9) / 10;

    HAL_UART_Transmit(uart->huart, (uint8_t *)data, len, HAL_UART_TRANSMIT_TIMEOUT);
}

void HalUartConfig(uint8_t uartNum, HalUartConfig_t *config)
{
    HalUart_t *uart = &g_uart[uartNum];
    if (config->baudrate != uart->huart->Init.BaudRate)
    {
        uart->huart->Init.BaudRate = config->baudrate;
        if (HAL_UART_Init(uart->huart) != HAL_OK)
        {
            // while(1);
        }
    }

    __HAL_UART_CLEAR_IDLEFLAG(uart->huart);
    if (config->dmaRxEnable)
    {
        HAL_UART_DMAStop(uart->huart);
        __HAL_UART_ENABLE_IT(uart->huart, UART_IT_IDLE);
        HAL_UART_Receive_DMA(uart->huart, config->dmaBuff, config->bufflen);
    }
    else
    {
        HAL_UART_Receive_IT(uart->huart, uart->recvBuff, 1); // enable interrupt
    }

    uart->config = *config;
}

void HalUartInitialize(void)
{
    memset(g_uart, 0, sizeof(HalUart_t) * HAL_UART_COUNT);
    g_uart[HAL_UART_PORT_3].huart = &huart3;
}

// void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
// {
//     uint8_t i;

//     for(i = 0; i < HAL_UART_COUNT; i++)
//     {
//         if(huart == g_uart[i].huart)
//         {
//             g_uart[i].txCpltFlag = true;
//             break;
//         }
//     }
// }

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) // rx interrupt handle
{
    uint8_t i;
    HalUart_t *uart;

    for (i = 0; i < HAL_UART_COUNT; i++)
    {
        uart = &g_uart[i];

        if (huart == uart->huart && !uart->config.dmaRxEnable)
        {
            if (uart->config.recvCb != NULL)
            {
                uart->config.recvCb(&uart->recvBuff[0], 1);
            }
            HAL_UART_Receive_IT(huart, uart->recvBuff, 1); // enable interrupt
            break;
        }
    }
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if (huart->ErrorCode & HAL_UART_ERROR_ORE)
    {
        __HAL_UART_CLEAR_OREFLAG(huart);
    }
}

void UsrUartIdleIRQHandler(UART_HandleTypeDef *huart)
{
    uint8_t i;
    HalUart_t *uart;
    uint16_t length;

    for (i = 0; i < HAL_UART_COUNT; i++)
    {
        uart = &g_uart[i];

        if (huart == uart->huart && uart->config.dmaRxEnable)
        {
            if (SET == __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
            {
                __HAL_UART_CLEAR_IDLEFLAG(huart);

                HAL_UART_DMAStop(huart);

                length = uart->config.bufflen - __HAL_DMA_GET_COUNTER(huart->hdmarx);
                if (uart->config.recvCb != NULL)
                {
                    uart->config.recvCb(uart->config.dmaBuff, length);
                }
                HAL_UART_Receive_DMA(huart, uart->config.dmaBuff, uart->config.bufflen);
            }
            break;
        }
    }
}
